﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using BlueSkySOA.Core.Configuration;
using System.Net;
using System.Web;
using BlueSkySOA.Service.SMSService.ApplicationService.Common;
using System.IO;
using BlueSkySOA.Core.Logging;
using BlueSkySOA.Core.ProxyServer;
namespace BlueSkySOA.Service.SMSService.ApplicationService.WebSendSms
{
    public class SlingSmsProxy: ISendSmsProxy
    {
        private const int MAX_LENGTH = 160;          
        private const String MESSAGE_COUNTRY = "data[Message][country]";
        private const String MESSAGE_MESSAGE = "data[Message][message]";
        private const String MESSAGE_NUMBER = "data[Message][number]";
        private const String MESSAGE_TOKEN_KEY = "data[_Token][key]";
        private const String MESSAGE_TOKEN_FIELDS = "data[_Token][fields]";
        private const String MESSAGE_TOKEN_UNLOCKED = "data[_Token][unlocked]";
        private const string MESSAGE_SECURITY_CODE = "data[Message][security_code]";
        private const String METHOD_KEY = "_method";
        private HttpWebRequest myRequest;
        private IWebProxy _currentProxy;
       
        #region ISendSmsEngine Members
        public static string ProxyKey { 
            get 
            {
                return "SSS";
            }
        }
        public SendSmsPostData GeneratePostDataFor(Messaging.SendSmsRequest sendSmsRequest)
        {
            SendSmsPostData postDataResult = new SendSmsPostData();
            postDataResult.WebSmsUrl = ApplicationSettingsFactory.GetApplicationSettings().GetValueForKeyFromAppSetting(ProxyKey);
            postDataResult.PostDataAndValue = new Dictionary<String, String>();
            postDataResult.PostDataAndValue.Add(METHOD_KEY, "POST");
            postDataResult.PostDataAndValue.Add(MESSAGE_COUNTRY, String.Empty);
            postDataResult.PostDataAndValue.Add(MESSAGE_MESSAGE, String.Empty);
            postDataResult.PostDataAndValue.Add(MESSAGE_NUMBER, String.Empty);
            postDataResult.PostDataAndValue.Add(MESSAGE_TOKEN_KEY, String.Empty);
            postDataResult.PostDataAndValue.Add(MESSAGE_TOKEN_FIELDS, String.Empty);
            postDataResult.PostDataAndValue.Add(MESSAGE_TOKEN_UNLOCKED, String.Empty);
            
            int numberOfSpaceWillBeAdded = MAX_LENGTH - sendSmsRequest.Message.Length;             
            StringBuilder buildMessage = new StringBuilder();
            buildMessage.Append(sendSmsRequest.Message);
            for (int i = 0; i < numberOfSpaceWillBeAdded; i++)
            {
                buildMessage.Append(" ");
            }
            postDataResult.PostDataAndValue[MESSAGE_COUNTRY] = sendSmsRequest.Country;
            postDataResult.PostDataAndValue[MESSAGE_MESSAGE] = buildMessage.ToString();
            postDataResult.PostDataAndValue[MESSAGE_NUMBER] = sendSmsRequest.PhoneNumber;
            return postDataResult;
        }

        public PostSmsDataResult HandleCallback(Messaging.SendSmsRequest sendSmsRequest, Dictionary<String, String> collection, IServerProxy serverProxy)
        {
            PostSmsDataResult webSendResult = new PostSmsDataResult();
            //sending sms
            try
            {
                //step 1: execute get request for getting token data
                if (InitializeGetRequest(collection, serverProxy))
                {
                    string response = ExecuteHttpRequest(collection);
                    if (response.Length > 0)
                    {
                        string successFlag = "Your message has been sent.";
                        if (response.Contains(successFlag))
                        {
                            webSendResult.Result = true;
                        }
                        else
                        {
                            if (response.Contains("MessageSecurityCode"))
                            {
                                string sumCaptcha = response.Substring(response.IndexOf("MessageSecurityCode"));
                                sumCaptcha = sumCaptcha.Substring("MessageSecurityCode".Length, sumCaptcha.IndexOf("</label>"));
                                string[] extractNumbers = Regex.Split(sumCaptcha, "[^\\d+]");
                                int sumResult = 0;
                                foreach (string s in extractNumbers)
                                {
                                    int parseValue = 0;
                                    if (int.TryParse(s, out parseValue))
                                    {
                                        sumResult += parseValue;
                                    }
                                }
                                if (!collection.ContainsKey(MESSAGE_SECURITY_CODE))
                                {
                                    collection.Add(MESSAGE_SECURITY_CODE, String.Empty);
                                }
                                collection[MESSAGE_SECURITY_CODE] = sumResult.ToString();
                                InititalPostRequest();
                                ParseTokenData(collection, response);
                                myRequest.Headers["Cookie"] = myRequest.GetResponse().Headers["Set-Cookie"];
                                return HandleCallback(sendSmsRequest, collection, serverProxy);
                            }
                        }
                    }
                    else
                    {
                        webSendResult.Result = false;
                    }
                }

                
            }
            catch (Exception ex)
            {
                webSendResult.Result = false;
                ILogger logger = LoggingFactory.GetLogger();
                if(logger!= null)
                    logger.Log(ex.ToString());
            }           
            return webSendResult;           
        }

        private bool InitializeGetRequest(Dictionary<String, String> collection, IServerProxy serverProxy)
        {
            bool resultValue = true;
            
            
            string response = "";
            try
            {
                HttpWebRequest request =
                        (HttpWebRequest)WebRequest.Create(ApplicationSettingsFactory.GetApplicationSettings().GetValueForKeyFromAppSetting(ProxyKey));
                request.Method = "GET";
                request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0";
                request.Credentials = CredentialCache.DefaultCredentials;
                if (serverProxy != null) _currentProxy = serverProxy.GetNextWebProxy();
                request.Proxy = _currentProxy;
                if (request.GetResponse().GetResponseStream() != null)
                {
                    using (StreamReader streamIn =
                               new StreamReader(request.GetResponse().GetResponseStream()))
                    {
                        response = streamIn.ReadToEnd();
                    }
                    ParseTokenData(collection, response);
                    if (myRequest == null)
                        InititalPostRequest();
                    myRequest.Headers["Cookie"] = request.GetResponse().Headers["Set-Cookie"];
                }
                else
                {
                    //proxy error
                    if (_currentProxy != null && serverProxy != null)
                    {
                        serverProxy.RemoveWebProxy(_currentProxy);
                        return InitializeGetRequest(collection, serverProxy);
                    }
                }
            }
            catch (Exception ex)
            {
                //proxy error
                if (_currentProxy != null && serverProxy != null)
                {
                    serverProxy.RemoveWebProxy(_currentProxy);
                    return InitializeGetRequest(collection, serverProxy);
                }
                resultValue = false;
            }
            return resultValue;
        }

        private void ParseTokenData(Dictionary<String, String> collection, string response)
        {
            string tokenKeyExpression = @"name=""data(\[)_Token(\])(\[)key(\])""(\s)*value=""(?<TokenKey>[\d\w%-_]*)""";
            string tokenFieldsExpression = @"name=""data(\[)_Token(\])(\[)fields(\])""(\s)*value=""(?<TokenFields>[\d\w%-_]*)""";
            string tokenUnlockedExpression = @"name=""data(\[)_Token(\])(\[)unlocked(\])""\s*value=""(?<TokenUnlocked>[\d\w%-_]*)""";
            if (!string.IsNullOrEmpty(response))
            {
                Regex regex = new Regex(tokenKeyExpression);
                Match match = regex.Match(response);
               
                if (match.Success)
                {
                    collection[MESSAGE_TOKEN_KEY] = match.Groups["TokenKey"].ToString();
                }
                regex = new Regex(tokenFieldsExpression);
                match = regex.Match(response);
                if (match.Success)
                {
                    collection[MESSAGE_TOKEN_FIELDS] = match.Groups["TokenFields"].ToString();
                }
                regex = new Regex(tokenUnlockedExpression);
                match = regex.Match(response);
                if (match.Success)
                {
                    collection[MESSAGE_TOKEN_UNLOCKED] = match.Groups["TokenUnlocked"].ToString();
                }
            }
            
        }

        private string ExecuteHttpRequest(Dictionary<String, String> collection)
        {
            byte[] byteArray = Encoding.ASCII.GetBytes(collection.ToQueryString());            
            myRequest.ContentLength = byteArray.Length;
            Stream dataStream = myRequest.GetRequestStream();
            dataStream.Write (byteArray, 0, byteArray.Length);
            string response = "";
            using (StreamReader streamIn =
                           new StreamReader(myRequest.GetResponse().GetResponseStream()))
            {
                 response = streamIn.ReadToEnd();
             }
            return response;
        }

        private void InititalPostRequest()
        {
            myRequest = (HttpWebRequest)WebRequest.Create(ApplicationSettingsFactory.GetApplicationSettings().GetValueForKeyFromAppSetting(ProxyKey));
            myRequest.Method = "POST";
            myRequest.AllowAutoRedirect = true;
            myRequest.ContentType = "application/x-www-form-urlencoded";
            myRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; rv:13.0) Gecko/20100101 Firefox/13.0.1";
            myRequest.Proxy = _currentProxy;
        }

        #endregion

        
    }
}
